package com.molichuxing.gateway.bff.car.services.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.CollectionUtils;
import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.gateway.bff.car.convertor.Convert;
import com.molichuxing.gateway.bff.car.entity.request.modify.CarsViolationModifyVo;
import com.molichuxing.gateway.bff.car.entity.response.CarsViolationVo;
import com.molichuxing.gateway.bff.car.services.ViolationBffService;
import com.molichuxing.services.business.dto.response.CarDetailBizDto;
import com.molichuxing.services.business.dto.response.CarOrderBizDto;
import com.molichuxing.services.business.dto.response.OrderBizDto;
import com.molichuxing.services.business.dto.response.OrderExclusivelBizDto;
import com.molichuxing.services.business.dto.response.OrderSubscribeBizDto;
import com.molichuxing.services.business.dto.response.UserBizDto;
import com.molichuxing.services.business.dto.response.ViolationBeanDto;
import com.molichuxing.services.business.service.CarBizService;
import com.molichuxing.services.business.service.ClxBizService;
import com.molichuxing.services.business.service.OrderBizService;
import com.molichuxing.services.business.service.UserBizService;
import com.molichuxing.services.business.service.VehicleBizService;
import com.molichuxing.services.infrastructure.dto.request.create.ViolationCreateDto;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.dto.response.CarsViolationDto;
import com.molichuxing.services.infrastructure.dto.response.OrderReturnDto;
import com.molichuxing.services.infrastructure.dto.response.StoreDto;
import com.molichuxing.services.infrastructure.dto.response.UserDto;
import com.molichuxing.services.infrastructure.dto.response.VehiclePictureDto;
import com.molichuxing.services.infrastructure.service.CarService;
import com.molichuxing.services.infrastructure.service.CarViolationService;
import com.molichuxing.services.infrastructure.service.OrderReturnService;
import com.molichuxing.services.infrastructure.service.StoreService;
import com.molichuxing.services.infrastructure.service.UserService;
import com.molichuxing.services.infrastructure.service.VehiclePictureService;
import com.molichuxing.services.property.CarViolationOpTypeEnum;
import com.molichuxing.services.property.OrderTypeEnum;

/**
 * 车辆检验bff
 * @author xuelin yi
 */
@Service("violationBffService")
public class ViolationBffServiceImpl implements ViolationBffService {

	private static final Logger logger = LoggerFactory.getLogger(ViolationBffServiceImpl.class);

	@Resource
	private CarViolationService carViolationService;

	@Resource
	private CarService carService;

	@Resource
	private UserService userService;

	@Resource
	private UserBizService userBizService;

	@Resource
	private VehicleBizService vehicleBizService;

	@Resource
	private OrderBizService orderBizService;

	@Resource
	private VehiclePictureService vehiclePictureService;
	
	@Resource
	private ClxBizService clxBizService;
	
	@Resource
	private CarBizService carBizService;
	
	@Resource
    private StoreService storeService;
	
	@Resource
	private OrderReturnService orderReturnService;

	@Override
	public List<CarsViolationVo> getCarsViolationByCarId(Integer carId) {
		List<CarsViolationDto> beanList = carViolationService.getCarsViolationByCarId(carId);
		return Convert.toCarsViolationVo(beanList, getUserMap(beanList));
	}


	/**
	 * 违章列表
	 * @param params
	 * @param pageNum
	 * @param pageSize
	 * @return
	 */
	@Override
	public Paged<CarsViolationVo> getCarsViolationPaged(Map<String, Object> params, Integer pageNum, Integer pageSize) throws Exception {
		Paged<CarsViolationVo> carsViolationVoPage = new Paged<>(null, 0, pageSize);

		if(null != params.get("userName")  && !"".equals(params.get("userName"))){
			UserDto userDto = userService.getUserByRealName(String.valueOf(params.get("userName")));
			if (null == userDto) {
				params.put("userId",0);
			}else {
				params.put("userId",userDto.getId());
			}
		}

		Paged<CarsViolationDto> carsViolationDtoPage = carViolationService.getCarsViolationPage(params,pageNum,pageSize);
		if (null == carsViolationDtoPage) {
			return carsViolationVoPage;
		}
		BeanUtils.copyProperties(carsViolationDtoPage, carsViolationVoPage);
		if (null == carsViolationDtoPage.getList() || carsViolationDtoPage.getList().size() <= 0) {
			return carsViolationVoPage;
		}

		List<CarsViolationVo> carsViolationVoList = new ArrayList<>();
		CarsViolationVo carsViolationVo = null;
		for (CarsViolationDto carsViolationDto:carsViolationDtoPage.getList()) {
			carsViolationVo =new CarsViolationVo();
			BeanUtils.copyProperties(carsViolationDto, carsViolationVo);
			//获取用户信息
			UserBizDto userBizDto = userBizService.getUser(carsViolationDto.getUserId());
			if(null != userBizDto) {
				carsViolationVo.setName(userBizDto.getName());
				carsViolationVo.setRealName(userBizDto.getRealName());
				carsViolationVo.setPhone(userBizDto.getPhone());
				carsViolationVo.setIdNumber(userBizDto.getIdNumber());
			}
			//根据车辆id获取车型信息
			CarDto carDto = carService.getCarById(carsViolationVo.getCarId());
			if(null != carDto) {
				carsViolationVo.setVehicleName(vehicleBizService.getVehicleName(carDto.getVehicleId()));
			}
			// 查询订单信息
			OrderBizDto orderBizDto = orderBizService.getOrder(carsViolationVo.getOrderCode());
			if (orderBizDto != null) {
				/*logger.error("订单({})不存在", carsViolationVo.getOrderCode());
				throw new BizException(OrderExceptionCodeEnum.NOT_EXIST.getCode(), "订单不存在");*/
				// 判断订单业务类型
				OrderTypeEnum orderType = orderBizDto.getType();
				Integer orderStatus = 0;
				if (OrderTypeEnum.EXCLUSIVEL.equals(orderType)) {
					// 专属里程订单
					OrderExclusivelBizDto orderExclusivelBizDto = (OrderExclusivelBizDto) orderBizDto;
					orderStatus = orderExclusivelBizDto.getOrderStatus().getValue();
				} else if (OrderTypeEnum.SUBSCRIBE.equals(orderType)) {
					// 订阅里程订单
					OrderSubscribeBizDto orderSubscribeBizDto = (OrderSubscribeBizDto) orderBizDto;
					orderStatus = orderSubscribeBizDto.getOrderStatus().getValue();
				}
				carsViolationVo.setOrderStatus(orderStatus);
				carsViolationVo.setOrderType(orderType.getValue());
			}
			carsViolationVo.setStatisticsTime(DateUtil.getViolationStatisticsTimeStr(new Date()));
			List<VehiclePictureDto> pictures = vehiclePictureService.getVehiclePictureByVehicleId(carDto.getVehicleId());
			if (pictures != null && !pictures.isEmpty()) {
				for (VehiclePictureDto picture : pictures) {
					if (picture.getIsWhiteBg() && 1 == picture.getPicDetailType()) {
						carsViolationVo.setVehicleImg(picture.getServerUrl());
						break;
					}
				}
			}
			carsViolationVoList.add(carsViolationVo);
		}
		carsViolationVoPage.setList(carsViolationVoList);
		return carsViolationVoPage;
	}


	private Map<Integer, UserBizDto> getUserMap(List<CarsViolationDto> beanList) {
		Map<Integer, UserBizDto> result = new HashMap<>();
		if((null != beanList)&&(beanList.size() > 0)) {
			List<Integer> userIds = new ArrayList<>();
			for(CarsViolationDto bean : beanList) {
				userIds.add(bean.getUserId());
			}
			result = userBizService.getUsers(userIds);
		}
		return result;
	}
	
	@Override
	public Boolean modifyStatusById(CarsViolationModifyVo modifyVo) {
        Assert.notNull(modifyVo,"参数不能为空");		
        Assert.notNull(modifyVo.getId(),"id不能为空");		
        Assert.notNull(modifyVo.getType(),"type不能为空");		
		return carViolationService.modifyStatusAndOpTypeById(modifyVo.getId(),modifyVo.getType());
	}
	
	@Override
	public Paged<CarsViolationVo> getCarsViolationQueryPaged(Map<String, Object> params, Integer pageNum,
			Integer pageSize) throws Exception {
		String vin = ObjectCastUtil.castString(params.get("vin"));
		CarDto carDto = carService.getCarByVin(vin);
        if(null == carDto) {
            throw new BizException(101,"不存在该车辆信息");
        }
        Integer carId = carDto.getId();
        CarDetailBizDto carDetailBizDto = carBizService.getCarDetail(carId);
		ResponseResult<List<ViolationBeanDto>> responseResult = clxBizService.getCxyViolation(carDto.getLicencePlate(), carDto.getVin(), carDetailBizDto.getEngineCode());
		Integer code = responseResult.getCode();
		/*
		 * 1008 	有违章 	计费
		 * 1009 	无违章 	计费
		 */
		if(code.equals(1008)) {
			List<ViolationBeanDto> data = responseResult.getData();
			//处理违章数据
			getCarsViolation(data, carId,  carDetailBizDto);
			return getCarsViolationPaged(params,  pageNum,  pageSize);
		}else if(code.equals(1009)) {
			 //如果无违章  则验证本地库是否存在违章 ，如果存在则修改状态（改为违章已处理）
             carViolationService.modifyViolationStatusByCarId(carId);
			 return new Paged<>(null, 0, pageSize);
		}
		throw new BizException(code,responseResult.getMessage());
	}
	
	/**
	 * 处理违章数据
	 * @param data
	 * @param carId
	 * @param carDetailBizDto
	 * @throws Exception
	 */
	private void getCarsViolation(List<ViolationBeanDto> data,Integer carId, CarDetailBizDto carDetailBizDto) throws Exception {
		// 根据车辆id查询所有对应的订单号
        List<CarOrderBizDto> carOrderBizDtoList = orderBizService.getOrderByCar(carId);

        //查询之前先把状态置为已处理已缴费
        carViolationService.modifyViolationStatusByCarId(carId);

        for (ViolationBeanDto violationBeanDto:data) {
        	 /**
             * 查询该条违章是否 《标记为已缴费》 
             * 标记为已缴费的 就不需要在按照第三方的状态，
             * 默认按照已缴费 不用给用户发短信等信息
             */
            CarsViolationDto carsViolationDto = carViolationService.getCarsViolationDto(null,carId,violationBeanDto.getRegulationTime());
            if(null != carsViolationDto) {
            	Integer opType = Integer.valueOf(carsViolationDto.getOpType());
            	if(CarViolationOpTypeEnum.MARK_PAID.getValue().equals(opType)) {
            		continue;
            	}
            }
        	
            if(CollectionUtils.isEmpty(carOrderBizDtoList)) {
                // 保存违章信息 无订单信息的违章
                violation(violationBeanDto,carDetailBizDto,null);
                continue;
            }
            
            
            for (CarOrderBizDto carOrderBizDto : carOrderBizDtoList) {
                if (null == carOrderBizDto.getDeliveryTime()) {
                    continue;
                }
                //违章时间 > 提车时间
                if(violationBeanDto.getRegulationTime().isAfter(carOrderBizDto.getDeliveryTime())) {

                    //查询该订单的还车时间
                    OrderReturnDto orderReturnDto = orderReturnService.getOrderReturn(carOrderBizDto.getOrderCode());

                    //该订单未还车 或者 违章时间 < 还车时间
                    if(null == orderReturnDto || violationBeanDto.getRegulationTime().isBefore(orderReturnDto.getReturnTime())){
                        // 保存违章信息
                        violation(violationBeanDto,carDetailBizDto,carOrderBizDto);
                    }
                }
            }
        }
	}
	
	  private void violation(ViolationBeanDto violationBeanDto,CarDetailBizDto carDetailBizDto,CarOrderBizDto carOrderBizDto) throws Exception {
	        //根据用户id，车辆id，违章时间查询库中是否有数据
	        CarsViolationDto carsViolationDto = carViolationService.getCarsViolationDto(null,carDetailBizDto.getCarId(),violationBeanDto.getRegulationTime());
	        if(null == carsViolationDto){
	            //如果没数据，则新建违章表
	            createViolation(carOrderBizDto,violationBeanDto,carDetailBizDto);
	        }else{
	            //如果有数据，判断当前违章状态是否与库中一致，不一致则更新数据库
	        	Integer status = Integer.valueOf(carsViolationDto.getStatus());
	        	Integer opType = Integer.valueOf(carsViolationDto.getOpType());
	        	if(!CarViolationOpTypeEnum.MARK_PAID.getValue().equals(opType)) {
	        		if(!status.equals(violationBeanDto.getStatus())){
	                    updateViolationById(carsViolationDto,violationBeanDto);
	                }
	        	}
	            
	        }
	  }
	  
	   /**
	     * 更新违章
	     * @param carsViolationDto
	     * @return
	     */
	    private void updateViolationById(CarsViolationDto carsViolationDto,ViolationBeanDto violationBeanDto) throws Exception {
	        //不一致则更新数据库
	        ViolationCreateDto violationCreateDto = new ViolationCreateDto();
	        violationCreateDto.setId(carsViolationDto.getId());
	        violationCreateDto.setStatus((byte)violationBeanDto.getStatus().intValue());
	        if(null != violationBeanDto.getHandlingTime() ){
	            violationCreateDto.setHandlingTime(violationBeanDto.getHandlingTime());
	        }
	        violationCreateDto.setGmtModified(LocalDateTime.now());
	        int ret = carViolationService.updateById(violationCreateDto);
	        if(ret < 0){
	            logger.error("更新违章信息失败,CarId:"+carsViolationDto.getCarId());
	        }
	    }

	  
	  /**
	     * 创建违章
	     * @param carOrderBizDto
	     * @param violationBeanDto
	     * @param carDetailBizDto
	     * @return
	     * @throws Exception
	     */
	    private void createViolation(CarOrderBizDto carOrderBizDto,ViolationBeanDto violationBeanDto,CarDetailBizDto carDetailBizDto) throws Exception {


	        ViolationCreateDto violationCreateDto = new ViolationCreateDto();
	        BeanUtils.copyProperties(violationBeanDto,violationCreateDto);
	        violationCreateDto.setCarId(carDetailBizDto.getCarId());
	        violationCreateDto.setVin(carDetailBizDto.getVin());
	        violationCreateDto.setFineFee(new BigDecimal(violationBeanDto.getFineFee()));
	        violationCreateDto.setStatus(violationBeanDto.getStatus().byteValue());
	        violationCreateDto.setEngineCode(carDetailBizDto.getEngineCode());

	        //无对应的订单信息
	        if(null != carOrderBizDto){
	            //根据门店id查询经销商信息
	            StoreDto storeDto = storeService.getStoreById(carOrderBizDto.getDeliveryStoreId());
	            if(null == storeDto){
	                logger.error("根据门店id查询经销商信息异常 门店Id："+ carOrderBizDto.getDeliveryStoreId());
	            }
	            violationCreateDto.setOrderCode(carOrderBizDto.getOrderCode());
	            violationCreateDto.setDealerId(storeDto == null ? null : storeDto.getDealerId());
	            violationCreateDto.setUserId(carOrderBizDto.getUserId());
	        }

	        int ret = carViolationService.createViolation(violationCreateDto);
	        if(ret < 0){
	            logger.error("新建违章信息失败,CarId:"+carDetailBizDto.getCarId());
	        }
	    }

}
